package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.utils.ThreadLocalUtil;
import com.itheima.reggie.web.R;
import com.itheima.reggie.entity.Employee;
import com.itheima.reggie.entity.dto.LoginDto;
import com.itheima.reggie.entity.dto.PageDto;
import com.itheima.reggie.mapper.EmployeeMapper;
import com.itheima.reggie.service.EmployeeService;
import com.itheima.reggie.web.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;

/**
 * 员工业务层实现类
 *
 * @Author Vsunks.v
 * @Blog blog.sunxiaowei.net/996.mba
 * @Description: 员工业务层实现类，继承ServiceImpl<EmployeeDao, Employee>，并且实现接口EmployeeService
 */
@Slf4j
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {

    // 注入session以获取当前登录用户的id   使用ThreadLocal优化并解耦
    // @Autowired
    // HttpSession session;

    /**
     * 登录
     *
     * @param loginDto 等录参数
     * @return 是否成功
     */
    @Override
    public R<Employee> login(LoginDto loginDto) {

        // 0. 参数校验
        String username = loginDto.getUsername();
        String password = loginDto.getPassword();
        if (StringUtils.isNotEmpty(username) && StringUtils.isNotEmpty(password)) {

            // 根据用户名查询
            // 封装查询条件
            LambdaQueryWrapper<Employee> qw = Wrappers.lambdaQuery(Employee.class).eq(Employee::getUsername, username);
            Employee employee = this.getOne(qw);

            // 1. 判断员工是否存在
            if (employee == null) {
                return R.fail("查无此人");
            }

            // 2. 加密提交的`password`，得到密文
            String pwd = DigestUtils.md5DigestAsHex(password.getBytes());

            // 3. 判断密码是否正确
            if (!pwd.equals(employee.getPassword())) {
                return R.fail("密码错误");
            }

            // 4. 判断员工是否被禁用
            if (employee.getStatus() == 0) {
                return R.fail("都离职了，还想干啥！！");
            }


            // 5. 登陆成功，把员工`ID`存入`session`  web层实现
            // 6. 响应登录成功数据到前台
            // 脱敏处理，敏感数据不要响应到前端
            //  方式1：employee手动set为空
            //  方式2：查询的时候不查
            //  方式3：封装一个新的实体对象 vo

            employee.setPassword("");

            return R.success("登录成功", employee);

        }
        return R.fail("参数有误");
    }

    /**
     * 新增用户
     *
     * @param employee 要保存的用户信息
     * @return 是否保存成功
     */
    @Override
    public R initAndSave(Employee employee) {

        // 1. 设置并加密密码
        String pwd = DigestUtils.md5DigestAsHex("123456".getBytes());
        employee.setPassword(pwd);

        // 2. 设置基础信息
        // 2.1 获取当前登录用户的id
        // Long employeeId = (Long) session.getAttribute("employee");
        // Long employeeId = ThreadLocalUtil.getCurrentId();
        //
        // employee.setCreateUser(employeeId);
        // employee.setUpdateUser(employeeId);
        // employee.setCreateTime(LocalDateTime.now());
        // System.out.println("LocalDateTime.now() = " + LocalDateTime.now());
        // employee.setUpdateTime(LocalDateTime.now());

        // 3. 保存
        boolean result = this.save(employee);

        if (result) {
            return R.success("新增员工成功！");
        }
        return R.fail("新增员工失败！");
    }

    /**
     * 新增用户，并检查用户名是否重复
     *
     * @param employee 要保存的用户信息
     * @return 是否保存成功
     */
    @Override
    public R saveWithNameCheck(Employee employee) {

        // 根据用户名查询用户
        String username = employee.getUsername();
        LambdaQueryWrapper<Employee> qw = Wrappers.lambdaQuery(Employee.class)
                .eq(StringUtils.isNotBlank(username), Employee::getUsername, username);

        Employee employeeInDb = this.getOne(qw);
        // 如果用户不为null，则表示已经存在，抛出重复的自定义异常。
        if (employeeInDb != null) {
            throw new BusinessException("用户名[" + username + "]重复，请修改后再试！");
        }

        // 1. 设置并加密密码
        String pwd = DigestUtils.md5DigestAsHex("123456".getBytes());
        employee.setPassword(pwd);

        // 2. 设置基础信息
        // 2.1 获取当前登录用户的id
        // Long employeeId = (Long) session.getAttribute("employee");
        // Long employeeId = ThreadLocalUtil.getCurrentId();
        //
        //
        // employee.setCreateUser(employeeId);
        // employee.setUpdateUser(employeeId);
        // employee.setCreateTime(LocalDateTime.now());
        // System.out.println("LocalDateTime.now() = " + LocalDateTime.now());
        // employee.setUpdateTime(LocalDateTime.now());

        // 3. 保存
        boolean result = this.save(employee);

        if (result) {
            return R.success("新增员工成功！");
        }
        return R.fail("新增员工失败！");
    }

    /**
     * 分页条件查询
     *
     * @param pageDto 分页参数和查询参数封装的实体类
     * @return 查询结果
     */
    @Override
    public R<Page<Employee>> page(PageDto pageDto) {

        // 手动校验并赋值
        Integer pageNum = pageDto.getPage();
        if (pageNum == null) {
            pageDto.setPage(1);
        }
        Integer pageSize = pageDto.getPageSize();
        if (pageSize == null) {
            pageDto.setPageSize(5);
        }

        // 1. 构造分页条件，并设置分页参数
        Page<Employee> page = new Page<>(pageDto.getPage(), pageDto.getPageSize());

        // 2. 构建搜索条件 - name进行模糊匹配
        String name = pageDto.getName();
        LambdaQueryWrapper<Employee> qw = Wrappers.lambdaQuery(Employee.class)
                .like(StringUtils.isNotBlank(name), Employee::getName, name);

        // 3. 构建排序条件 - 更新时间倒序排序
        qw.orderByDesc(Employee::getUpdateTime);

        // 4. 执行查询
        this.page(page, qw);

        // 5. 组装结果并返回
        return R.success("分页查询员工成功", page);
    }


    /**
     * 重写按照id按需更新的方法，更新前校验用户名是否重复。
     *
     * @param entity 要修改的员工信息
     * @return 是否修改成功
     */
    @Override
    public boolean updateById(Employee entity) {
        // 记录线程名称，用于验证同一个请求是否是一个线程
        // log.error("线程信息：{}",Thread.currentThread().getName());

        String username = entity.getUsername();

        if (StringUtils.isNotBlank(username)) {
            // 根据用户名等值匹配查询
            LambdaQueryWrapper<Employee> qw = Wrappers.lambdaQuery(Employee.class)
                    .eq(Employee::getUsername, username)
                    .ne(Employee::getId,entity.getId());

            Employee employeeInDb = this.getOne(qw);

            // 如果查到，则重复，提示xxx重复
            if (employeeInDb != null) {
                throw new BusinessException("用户名[" + username + "]重复，请修改后再试！");
            }

        }
        // 否则不重复，提交修改
        return super.updateById(entity);
    }
}
